#include "gpio.h"

/*function:io_group_get
 *feature:interior call function,get io group.
 *input:pin: io pin.
 *output:dat:io group. 
 *time:2024/11/25
 */
static uint32_t io_group_get(gpio_pin_enum pin)
{
    uint32_t port_type;
    switch(io_group(pin))
    {
        case 0x00: rcu_periph_clock_enable(RCU_GPIOA); port_type = GPIOA; break;
        case 0x01: rcu_periph_clock_enable(RCU_GPIOB); port_type = GPIOB; break;
        case 0x02: rcu_periph_clock_enable(RCU_GPIOC); port_type = GPIOC; break;
        case 0X03: rcu_periph_clock_enable(RCU_GPIOD); port_type = GPIOD; break;
        case 0X04: rcu_periph_clock_enable(RCU_GPIOF); port_type = GPIOF; break;
    }
    return port_type;
}

/*function:af_group_get
 *feature:interior call function,get af group.
 *input:pin: af enum.
 *output:dat:af group. 
 *time:2024/11/27
 */
static uint32_t af_group_get(gpio_af_enum af)
{
    uint32_t af_type, i;
    for(i = 0; i <= GPIO_AF7; i++)
    {
        if(i == af)
        {
            af_type = AF(i);
        }
    }
    return af_type;
}
/*function:io_read
 *feature:read io pin bit.
 *input:pin: io pin(Select from the gpio_pin_enum enum of gpio.h)
 *output:dat:io pin port bit. 
 *e.g. io_read(A3);
 *time:2024/11/26 
 */ 
FlagStatus io_read(gpio_pin_enum pin)
{
    uint32_t io_type;
    io_type = io_group_get(pin);
    if((uint32_t)RESET != (GPIO_ISTAT(io_type) & (GPIO_PIN_0 << io_pin(pin))))
        {return SET;}
    else 
        {return RESET;}
}

/*function:io_write
 *feature:write io pin bit.
 *input:pin: io pin(Select from the gpio_pin_enum enum of gpio.h).
 *      dat: SET or RESET.
 *output:none 
 *e.g. io_write(A3, SET);
 *time:2024/11/26
 */
void io_write(gpio_pin_enum pin, FlagStatus dat)
{
    uint32_t io_type;
    io_type = io_group_get(pin);
    if(dat == SET)
        GPIO_BOP(io_type) = (GPIO_PIN_0 << io_pin(pin));
    else
        GPIO_BC(io_type) = (GPIO_PIN_0 << io_pin(pin));
}

/*function:io_toggle
 *feature:toggle io pin bit.
 *input:pin: io pin(Select from the gpio_pin_enum enum of gpio.h).
 *output:none 
 *e.g. io_write(A3);
 */
void io_toggle(gpio_pin_enum pin)
{
    uint32_t io_type;
    io_type = io_group_get(pin);
    GPIO_TG(io_type) = (GPIO_PIN_0 << io_pin(pin));
}

/*function:gpio_init
 *feature:init gpio port.
 *input:pin: io pin(Select from the gpio_pin_enum enum of gpio.h)
 *      dir: io direction (Select from the gpio_dir_enum enum of gpio.h)
 *      dat: io out electric level (Select from the gpio_level_enum enum of gpio.h)
 *      pinmode: io input or output mode (Select from the gpio_mode_enum enum of gpio.h)
 * output:none
 * e.g. gpio_init(A0, GPI, GPIO_LOW, GPI_PULL_DOWN);
 *      gpio_init(A1, GPO, GPIO_HIGH, GPO_PUSH_PULL);
 * time:2024/11/20
 */
void gpio_init(gpio_pin_enum pin, gpio_dir_enum dir, uint8_t dat, gpio_mode_enum pinmode)
{
    uint32_t io_type;
    io_type = io_group_get(pin);

    switch(dir)
    {
        case GPI: {
            if(pinmode == GPI_NONE_IN)
                gpio_mode_set(io_type, GPIO_MODE_INPUT, GPIO_PUPD_NONE, (GPIO_PIN_0 << io_pin(pin))); 
            else if(pinmode == GPI_PULL_UP)
                gpio_mode_set(io_type, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, (GPIO_PIN_0 << io_pin(pin))); 
            else
                gpio_mode_set(io_type, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, (GPIO_PIN_0 << io_pin(pin))); 
            break;}

        case GPO: {
            if(pinmode == GPO_PUSH_PULL)
                {
                    gpio_mode_set(io_type, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, (GPIO_PIN_0 << io_pin(pin)));
                    gpio_output_options_set(io_type, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, (GPIO_PIN_0 << io_pin(pin)));
                }
            if(pinmode == GPO_OPEN_DTAIN)
                {
                    gpio_mode_set(io_type, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, (GPIO_PIN_0 << io_pin(pin)));
                    gpio_output_options_set(io_type, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, (GPIO_PIN_0 << io_pin(pin)));
                }
            break;}
    }
}

/*function:afio_init
 *feature:init afio port.
 *input:pin: io pin(Select from the gpio_pin_enum enum of gpio.h)
 *      dir: io direction (Select from the gpio_dir_enum enum of gpio.h)
 *      dat: io out electric level (Select from the gpio_level_enum enum of gpio.h)
 *      pinmode: io input or output mode (Select from the gpio_mode_enum enum of gpio.h)
 * output:none
 * e.g. afio_init(A0, GPI, GPIO_LOW, GPI_PULL_DOWN);
 *      afio_init(A1, GPO, GPIO_HIGH, GPO_PUSH_PULL);
 * time:2024/11/20
 */
void afio_init(gpio_pin_enum pin, gpio_af_enum af, gpio_mode_enum pinmode)
{
    uint32_t io_type, af_type;
    io_type = io_group_get(pin);
    af_type = af_group_get(af);

    switch(pinmode)
    {
        case GPO_PUSH_PULL:{
            gpio_mode_set(io_type, GPIO_MODE_AF, GPIO_PUPD_NONE, (GPIO_PIN_0 << io_pin(pin)));
            gpio_output_options_set(io_type, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, (GPIO_PIN_0 << io_pin(pin)));
            gpio_af_set(io_type, af_type, (GPIO_PIN_0 << io_pin(pin)));
            break;
        }
        case GPO_OPEN_DTAIN:{
            gpio_mode_set(io_type, GPIO_MODE_AF, GPIO_PUPD_PULLUP, (GPIO_PIN_0 << io_pin(pin)));
            gpio_output_options_set(io_type, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, (GPIO_PIN_0 << io_pin(pin)));
            gpio_af_set(io_type, af_type, (GPIO_PIN_0 << io_pin(pin)));
            break;
        }
    }
    
}